package com.rd.animation.type;

import com.rd.animation.controller.ValueController;
import com.rd.animation.data.type.FillAnimationValue;
import com.rd.utils.AnimatorUtils;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;

public class FillAnimation extends ColorAnimation {

    public static final int DEFAULT_STROKE_DP = 1;

    private static final String ANIMATION_RADIUS_REVERSE = "ANIMATION_RADIUS_REVERSE";
    private static final String ANIMATION_RADIUS = "ANIMATION_RADIUS";

    private static final String ANIMATION_STROKE_REVERSE = "ANIMATION_STROKE_REVERSE";
    private static final String ANIMATION_STROKE = "ANIMATION_STROKE";


    private FillAnimationValue value;

    private int radius;
    private int stroke;

    public FillAnimation(ValueController.UpdateListener listener) {
        super(listener);
        value = new FillAnimationValue();
    }

    @Override
    public ValueAnimator createAnimator() {
        ValueAnimator animator = new ValueAnimator();
        animator.setDuration(BaseAnimation.DEFAULT_ANIMATION_TIME);
        animator.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        animator.setValueUpdateListener(
                new AnimatorValue.ValueUpdateListener() {
                    @Override
                    public void onUpdate(AnimatorValue animatorValue, float v) {
                        animator.onUpdate(animatorValue, v);
                        onAnimateUpdated(animatorValue);
                    }
                });

        return animator;
    }

    public FillAnimation with(int colorStart, int colorEnd, int radius, int stroke) {
        if (animator != null && hasChanges(colorStart, colorEnd, radius, stroke)) {
            this.colorStart = colorStart;
            this.colorEnd = colorEnd;

            this.radius = radius;
            this.stroke = stroke;

            PropertyValuesHolder colorHolder = createColorPropertyHolder(false);
            PropertyValuesHolder reverseColorHolder = createColorPropertyHolder(true);

            PropertyValuesHolder radiusHolder = createRadiusPropertyHolder(false);
            PropertyValuesHolder radiusReverseHolder = createRadiusPropertyHolder(true);

            PropertyValuesHolder strokeHolder = createStrokePropertyHolder(false);
            PropertyValuesHolder strokeReverseHolder = createStrokePropertyHolder(true);

            animator.setInnerListener(
                    new InnerValueUpdateListener() {
                        @Override
                        public void onUpdate(AnimatorValue animatorValue, float f) {
                            color = AnimatorUtils.getColor(f, colorHolder.getStartValue(), colorHolder.getEndValue());
                            colorReverse =
                                    AnimatorUtils.getColor(
                                            f, reverseColorHolder.getStartValue(), reverseColorHolder.getEndValue());
                            radiusOrigin =
                                    AnimatorUtils.getIntValue(
                                            radiusHolder.getStartValue(), radiusHolder.getEndValue(), f);
                            radiusReverse =
                                    AnimatorUtils.getIntValue(
                                            radiusReverseHolder.getStartValue(), radiusReverseHolder.getEndValue(), f);
                            strokeOrigin =
                                    AnimatorUtils.getIntValue(
                                            strokeHolder.getStartValue(), strokeHolder.getEndValue(), f);
                            strokeReverse =
                                    AnimatorUtils.getIntValue(
                                            strokeReverseHolder.getStartValue(), strokeReverseHolder.getEndValue(), f);
                        }
                    });
        }

        return this;
    }

    private PropertyValuesHolder createRadiusPropertyHolder(boolean isReverse) {
        int startRadiusValue;
        int endRadiusValue;

        if (isReverse) {
            startRadiusValue = radius / 2;
            endRadiusValue = radius;
        } else {
            startRadiusValue = radius;
            endRadiusValue = radius / 2;
        }

        PropertyValuesHolder holder = PropertyValuesHolder.ofInt(startRadiusValue, endRadiusValue);

        return holder;
    }

    private PropertyValuesHolder createStrokePropertyHolder(boolean isReverse) {
        int startStrokeValue;
        int endStrokeValue;

        if (isReverse) {
            startStrokeValue = radius;
            endStrokeValue = 0;
        } else {
            startStrokeValue = 0;
            endStrokeValue = radius;
        }

        PropertyValuesHolder holder = PropertyValuesHolder.ofInt(startStrokeValue, endStrokeValue);

        return holder;
    }

    int color;
    int colorReverse;
    int radiusOrigin;
    int radiusReverse;
    int strokeOrigin;
    int strokeReverse;

    private void onAnimateUpdated(AnimatorValue animation) {
        value.setColor(color);
        value.setColorReverse(colorReverse);

        value.setRadius(radiusOrigin);
        value.setRadiusReverse(radiusReverse);

        value.setStroke(strokeOrigin);
        value.setStrokeReverse(strokeReverse);

        if (listener != null) {
            listener.onValueUpdated(value);
        }
    }

    @SuppressWarnings("RedundantIfStatement")
    private boolean hasChanges(int colorStart, int colorEnd, int radiusValue, int strokeValue) {
        if (this.colorStart != colorStart) {
            return true;
        }

        if (this.colorEnd != colorEnd) {
            return true;
        }

        if (radius != radiusValue) {
            return true;
        }

        if (stroke != strokeValue) {
            return true;
        }

        return false;
    }
}
